Google Homeの喋らせ方
Google Home に、指定したテキストを喋らせる方法を説明する。
https://gyazo.com/87a308d770ae936e79c10365dd42bf77
手順の概要
準備にいささか手間はかかるが、初心者でも設定ができるよう、丁寧にステップ・バイ・ステップで手順を説明する。
もしまだ「hubot」や「Slack」「IFTTT」などを知らなければ、こちら → プレゼン資料(ほんの数分で読めます) この記事で行う手順の概要は、以下の通り。
次に、このUNIXコマンドを、sayという名前で、自宅のhubotサーバに登録する。
すると、send say(こんにちは)というメッセージをhubotに送るだけで、Google Homeが「こんにちは」と喋ってくれる。
hubotへのメッセージは、Slack経由で送ることができるで、IFTTT を使って、色々なことができるようになる。 google-home-notifierをインストール
以下は、MacやLinuxなどでの手順
code:sh
# Macの場合
$ cd ~/homebot # hubotのディレクトリに移動
$ npm install google-home-notifier --save
テキストをGoogle Homeに喋らせるUNIXコマンドを作る
次のようなファイル bin/say.js を作る。
(ファイルの編集には、nano というエディタを使う。nanoの使い方はこちら → nano) code:js
const home = require('google-home-notifier');
const argv = process.argv;
const text = argv2 || ''; const lang = argv3 || 'ja'; const device = argv4 || ''; home.device(device, lang);
home.notify(text, (res) => console.log('said '+ text));
ただし、このファイル bin/say.jsの1行目は、実行環境によっては修正が必要なことに注意。
次のように、nodeのPATHを調べて、/usr/local/bin/node と表示されるかを確認する。
code:sh
$ which node # nodeのパスを確認
/usr/local/bin/node
もし、which nodeの結果が/usr/local/bin/nodeではなく、例えば☆△◎だった場合は、#!/usr/local/bin/nodeを #!☆△◎ に書き換えればOK。
このファイルに実行権限を与えれば、UNIXコマンドとして実行できるようになる。
code:sh
$ chmod 755 bin/say.js
コマンドを実行して、Google Homeに喋らせる
bin/say.js に引数「こんにちは」を渡せば、Google Home が「こんにちは」と喋ってくれる。
code:sh
$ bin/say.js "こんにちは" # Google Homeに、テキスト「こんにちは」を、喋らせる
Device "Google-Home-123abc........." at 192.168.1.70:8009 # 検出された Google Home の名前が表示される
Device "Google-Home-456def........." at 192.168.1.71:8009
Device "Google-Cast-Group-EEE789..." at 192.168.1.70:42662 # Google Home のグループも表示される
said こんにちは # 喋ったテキストが表示される
なお、コマンドを実行してから、Google Home が喋るまでには、残念ながら 2〜3 秒かかる。
もし自宅にChromecastなどのCastデバイスがある場合には、Google Homeだけでなく、すべてのCastデバイスが「こんにちは」と喋るようになる。すぐ後で述べるように、Google Homeだけに喋らせたり、Chromecastだけに喋らせることも、細かく指定できるのでご安心を。 2番目の引数で言語を指定すれば、日本語(ja)や英語(en)を切り替えられる。
code:sh
$ bin/say.js "こんにちは" ja
$ bin/say.js "Hello" en
3番目の引数で Google Home の名前を指定すれば、指定された Google Home だけに喋らせることができる。
code:sh
$ bin/say.js "リビングから こんにちは" ja Google-Home-123abc
Google Homeの名前は、先頭部分だけが一致すればいいので、すべてを書く必要はない。
また、すべてのGoogle Homeに喋らせたければ、Google-Homeと指定すればよい。
UNIXコマンドを hubot に登録する
作ったhubotサーバに、Slackから次のメッセージを送れば、sayという名前で、hubot にUNIXコマンドが登録される。
homebot command say bin/say.js "#" ja Google-Home
⇒ 登録されると set !say to bin/say.js "#" ja Google-Home という返事が返ってくる
注意:Slackから登録する際に、クォートが勝手にバッククォートになることがある。Macの場合は、「システム環境設定」→「キーボード」→「ユーザ辞書」→「スマート引用符とスマートダッシュを使用」のチェックを外すことで解決できる。
コマンドの実行時には、与えられた引数が、# のところに、サニタイズ(後述)されてから、埋め込まれる。
例えば、say(こんにちは) を実行すると、bin/say.js "こんにちは" ja Google-Home が実行される。
Slack から Google Home を喋らせる
Slack 経由で hubot に次のメッセージを送れば、Google Home が「Slackからこんにちは」と喋ってくれる。
homebot send say(Slackからこんにちは)
⇒ 実行されると、実行されたコマンドの文字列 bin/say.js "Slackからこんにちは" ja Google-Home が返ってくる
Twitterでフォローされたら、Google Homeに喋らせる
次のような IFTTT アプレットを用意すればよい。 THIS
Twitter の「New follower」トリガーを選択する
THAT
Slack の「Post to channel」アクションを選択する
Which channel? 欄で、Private Groupと、homebot の参加しているプライベートグループを選択する
Private Group経由でなく、Direct Messageから直接@homebotに話しかけてもOK
Message 欄に、homebot send say({{FullName}}さんからフォローされました) を入力する。
Direct Messageの場合は、先頭のhomebot は不要
他の欄は空欄にする。
(用意したアプレットの内容が、Google Home に反映されるまでに、数十秒かかるので、焦らず待つ。)
以上で、いつか、誰かがフォローしてくれたら、Google Home が教えてくれるようになった。
Google Homeごとに、sayコマンドを用意する
台所だけ喋らせるコマンドsay:kitchenや、寝室だけ喋らせるコマンドsay:bedroomなどを、部屋ごとに用意しておくと、何かと便利。
台所のGoogle Homeの名前がGoogle-Home-123abcの場合は、
homebot command say:kitchen bin/say.js "#" ja Google-Home-123abc
としてsay:kitchenコマンドを登録しておけば、
homebot send say:kitchen(台所からこんにちは)
台所のGoogle Homeだけを喋らせることができる。
同様に、寝室のGoogle Homeの名前がGoogle-Home-456defなら、say:bedroomコマンドは、次のように登録する。
homebot command say:bedroom bin/say.js "#" ja Google-Home-456def
また、Google Homeだけでなく、すべてのCastデバイスに喋らせるコマンドsay:allは、次のように登録できる。
homebot command say:all bin/say.js "#"
時間帯を制限するUNIXコマンドを作る
就寝中はGoogle Homeに喋って欲しくないという場合のために、現在時刻が指定した時間帯のときだけ成功するUNIXコマンド bin/time.js を作る。このコマンドを使えば、例えば、07:30〜22:00の時間帯だけbin/say.jsを実行する、ということができるようになる。
code:js
const argv = process.argv;
const from = Number(argv2) || 0000; const to = Number(argv3) || 2400; const n = new Date;
const now = n.getHours() * 100 + n.getMinutes();
const ok = from < to
? from <= now && now < to
: from <= now || now < to;
process.exit(ok ? 0 : 1);
先ほどのbin/say.jsと同じく、このファイルの1行目も、実行環境によっては修正が必要なことに注意。
作ったファイルに実行権限を与える。
code:sh
$ chmod 755 bin/time.js
07:30〜22:00の時間帯だけ、bin/say.jsを実行したい場合には、以下のようにすればよい。
code:sh
$ bin/time.js 0730 2200 && bin/say.js "こんにちは"
ここで、x && yは、コマンドxが成功した場合だけ(終了コードが0の場合だけ)、コマンドyを実行する。
コマンドbin/time.js 0730 2200は、現在時刻が07:30〜22:00の場合だけ成功するので、もし現在時刻が02:15ならbin/say.js "こんにちは"は実行されない。
このbin/time.jsは日付をまたぐ場合にも期待通りに動くので、例えば、23:15〜翌03:45の時間帯だけ、bin/say.jsを実行したければ、以下のようにする。
code:sh
$ bin/time.js 2315 0345 && bin/say.js "お疲れ様"
bin/say.js以外にも、色々なUNIXコマンドに応用できるので、覚えておくと便利だろう。
補足:UNIXコマンドに与える引数のサニタイズ
セキュリティに関する、少し難しい話をする。
UNIXコマンドに悪意のある引数を与えると、hubotが動いてるサーバで、悪意のあるコマンドが実行されてしまう恐れがある。
それを防ぐために、このシステムでは、引数をUNIXコマンドに渡す前に、引数をサニタイズ(消毒)する。
サニタイズでは、すべての半角記号と制御文字を、空白に置き換える。
例えば、rm -rf /という引数をサニタイズすると、半角記号 -と/が に置き換わって、rm rf になる。
上述のsayは、bin/say.js "#"というコマンドを実行することを思い出してほしい。
例えば、悪意のある引数 " ; rm -rf / ; echo " が与えれた場合、もしサニタイズされないまま、引数をコマンドに埋め込んでしまうと、
bin/say.js " " ; rm -rf / ; echo " "
が実行されてしまう。
しかし、このシステムでは、引数が自動的にサニタイズされるので、
bin/say.js " rm rf echo "
が実行され、悪意のあるコマンドは実行されずに済む。
このシステムには、以上のようなセキュリティ対策が施されているので、安心してsayコマンドを使うことができる。
2018/1/19